"""
GitCode API 客户端
独立实现，不依赖项目其他模块
"""
import os
import json
import ssl
import http.client
from typing import Optional, List, Dict, Tuple


class GitCodeClient:
    """GitCode API 客户端封装"""
    
    API_BASE = "api.gitcode.com"
    
    def __init__(self, token: str = None):
        """
        初始化客户端
        :param token: GitCode token，如果为 None 则从环境变量获取
        """
        self.token = token or os.getenv("gitcode_password") or os.getenv("gitcode_token")
        if not self.token:
            print("Warning: No GitCode token found. Set gitcode_password or gitcode_token environment variable.")
    
    def _make_request(self, method: str, path: str, body: dict = None, 
                     use_auth_header: bool = True) -> Tuple[int, dict]:
        """
        发送 HTTP 请求到 GitCode API
        :param method: HTTP 方法 (GET, POST, PUT, DELETE)
        :param path: API 路径
        :param body: 请求体（字典）
        :param use_auth_header: 是否使用 Authorization header（否则用 query param）
        :return: (status_code, response_dict)
        """
        context = ssl._create_unverified_context()
        conn = http.client.HTTPSConnection(self.API_BASE, context=context)
        
        headers = {
            'Content-Type': 'application/json',
            'Accept': 'application/json'
        }
        
        # 添加认证
        if self.token:
            if use_auth_header:
                headers['Authorization'] = f'Bearer {self.token}'
            else:
                # 使用 query parameter
                if '?' in path:
                    path = f"{path}&access_token={self.token}"
                else:
                    path = f"{path}?access_token={self.token}"
        
        # 准备请求体
        payload = ''
        if body:
            payload = json.dumps(body, ensure_ascii=False).encode('utf-8')
        
        try:
            conn.request(method, path, payload, headers)
            res = conn.getresponse()
            data = res.read().decode("utf-8", errors="ignore")
            
            try:
                parsed = json.loads(data) if data else {}
            except json.JSONDecodeError:
                parsed = {"raw_response": data}
            
            return res.status, parsed
        except Exception as e:
            return 0, {"error": str(e)}
        finally:
            try:
                conn.close()
            except Exception:
                pass
    
    def create_issue(self, owner: str, repo: str, title: str, body: str = "", template_path: str = None) -> Tuple[bool, dict]:
        """
        创建 Issue
        :param owner: 仓库所有者
        :param repo: 仓库名
        :param title: Issue 标题
        :param body: Issue 描述（如果提供了 template_path，则 body 中应包含 template_path 参数）
        :param template_path: 模板路径（如果提供，将在 body 中传递 template_path 参数而不是内容）
        :return: (success: bool, result: dict)
        """
        path = f"/api/v5/repos/{owner}/issues"
        
        # 如果提供了 template_path，则在 body 中传递 template_path 参数
        if template_path:
            # 将 template_path 作为 body 参数传递
            payload = {
                "repo": str(repo),
                "title": str(title),
                "body": f"template_path={template_path}"
            }
        else:
            payload = {
                "repo": str(repo),
                "title": str(title),
                "body": str(body) if body else ""
            }
        
        status, result = self._make_request("POST", path, payload)
        ok = 200 <= status < 300
        return ok, result
    
    def create_pr(self, owner: str, repo: str, title: str, head: str, base: str, 
                  body: str = "", fork_path: str = None, labels: List[str] = None) -> Tuple[bool, dict]:
        """
        创建 Pull Request
        :param owner: 仓库所有者
        :param repo: 仓库名
        :param title: PR 标题
        :param head: 源分支（格式：fork_user:branch_name）
        :param base: 目标分支
        :param body: PR 描述
        :param fork_path: Fork 路径（可选）
        :param labels: 标签列表（可选）
        :return: (success: bool, result: dict)
        """
        path = f"/api/v5/repos/{owner}/{repo}/pulls"
        payload = {
            "title": str(title),
            "head": str(head),
            "base": str(base),
            "body": str(body),
            "prune_source_branch": True,
            "squash": True
        }
        
        if fork_path:
            payload["fork_path"] = str(fork_path)
        if labels:
            payload["labels"] = ",".join([str(l).strip() for l in labels if l])
        
        status, result = self._make_request("POST", path, payload)
        ok = 200 <= status < 300
        return ok, result
    
    def get_issue_by_pr(self, repo: str, pr_number: int) -> Tuple[Optional[int], Optional[str]]:
        """
        根据 PR 号获取关联的 Issue
        :param repo: 仓库名
        :param pr_number: PR 编号
        :return: (issue_number: int, full_name: str) 或 (None, None)
        """
        full_name = f"Cangjie/{repo}"
        path = f"/api/v5/repos/{full_name}/pulls/{pr_number}/issues"
        
        status, result = self._make_request("GET", path, use_auth_header=False)
        
        if 200 <= status < 300 and isinstance(result, list) and len(result) > 0:
            issue = result[0]
            issue_number = issue.get('number')
            repo_full_name = issue.get("repository", {}).get("full_name")
            return issue_number, repo_full_name
        
        return None, None
    
    def get_prs_by_issue(self, repo: str, issue_number: int) -> List[dict]:
        """
        根据 Issue 号获取关联的 PR 列表
        :param repo: 仓库名
        :param issue_number: Issue 编号
        :return: PR 列表
        """
        path = f"/api/v5/repos/Cangjie/{repo}/issues/{issue_number}/pull_requests"
        
        status, result = self._make_request("GET", path, use_auth_header=False)
        
        if 200 <= status < 300 and isinstance(result, list):
            # 只返回状态为 open 的 PR
            return [pr for pr in result if pr.get("state") == "open"]
        
        return []
    
    def get_pr_commits(self, owner: str, repo: str, pr_number: int) -> Tuple[bool, List[dict]]:
        """
        获取 PR 的 commits 列表
        :param owner: 仓库所有者
        :param repo: 仓库名
        :param pr_number: PR 编号
        :return: (success: bool, commits: List[dict])
        """
        path = f"/api/v5/repos/{owner}/{repo}/pulls/{pr_number}/commits"
        
        status, result = self._make_request("GET", path, use_auth_header=False)
        
        if 200 <= status < 300:
            if isinstance(result, list):
                return True, result
            else:
                return False, [{"error": "Unexpected response format", "raw": result}]
        else:
            return False, [{"error": f"API request failed with status {status}", "raw": result}]
    
    def get_issue(self, owner: str, repo: str, issue_number: int) -> Tuple[bool, dict]:
        """
        获取 Issue 信息
        :param owner: 仓库所有者
        :param repo: 仓库名
        :param issue_number: Issue 编号
        :return: (success: bool, issue_info: dict)
        """
        path = f"/api/v5/repos/{owner}/{repo}/issues/{issue_number}"
        
        status, result = self._make_request("GET", path, use_auth_header=False)
        
        if 200 <= status < 300:
            return True, result
        else:
            return False, {"error": f"API request failed with status {status}", "raw": result}
    
    def get_pr(self, owner: str, repo: str, pr_number: int) -> Tuple[bool, dict]:
        """
        获取 PR 详细信息
        :param owner: 仓库所有者
        :param repo: 仓库名
        :param pr_number: PR 编号
        :return: (success: bool, pr_info: dict)
        """
        path = f"/api/v5/repos/{owner}/{repo}/pulls/{pr_number}"
        
        status, result = self._make_request("GET", path, use_auth_header=False)
        
        if 200 <= status < 300:
            return True, result
        else:
            return False, {"error": f"API request failed with status {status}", "raw": result}

